<?php

namespace Framework\Foundation\Database;

use iamcal\SQLParser;

class SchemaValidator
{
    protected $config;

    public function __construct($config = [])
    {
        if (!isset($config['ignoreField'])) {
            $this->config['ignoreField'] = [
                'status',
                'created_at',
                'updated_at',
                'is_deleted',
                'deleted_at',
            ];
        }
    }

    public function getValidatorBySql(string $sql, array $coverConf = [])
    {
        $sqlParser = new SQLParser();
        $schemaInfo = $sqlParser->parse($sql);

        return $this->getValidatorBySchema($schemaInfo, $coverConf);
    }

    public function getValidatorBySchema(array $schemaInfo, array $coverConf = [])
    {
        return $this->genRulesBySchema(current($schemaInfo)['fields'], $coverConf);
    }

    public function genRulesBySchema(array $fields, array $coverConf = [])
    {
        $rules = [];
        foreach ($fields as $fieldInfo) {
            if (in_array($fieldInfo['name'], $this->config['ignoreField'])) {
                continue;
            }

            if (isset($coverConf[$fieldInfo['name']])) {
                $rules[$fieldInfo['name']] = $coverConf[$fieldInfo['name']];
                continue;
            }

            $rules[$fieldInfo['name']] = $this->genRuleBySchemaInfo($fieldInfo);
        }

        return $rules;
    }

    // @link https://www.runoob.com/mysql/mysql-data-types.html
    // @link https://github.com/ircmaxell/filterus
    public function genRuleBySchemaInfo(array $fieldInfo)
    {
        $rule = '';
        switch ($fieldInfo['type']) {
            case 'TINYINT':
                $rule = 'int,max:3';
                break;
            case 'SMALLINT':
                $rule = 'int,max:5';
                break;
            case 'MEDIUMINT':
                $rule = 'int,max:8';
                break;
            case 'INT':
            case 'INTEGER':
                $rule = 'int,max:11';
                break;
            case 'BIGINT':
                $rule = 'int,max:20';
                break;
            case 'FLOAT':
            case 'DOUBLE':
            case 'DECIMAL':
                $rule = 'float,max:20';
                break;
            case 'DATE':
                $rule = 'regex,regex:/\d{4}-\d{2}-\d{2}/';
                break;
            case 'TIME':
                $rule = 'regex,regex:/\d{2}:\d{2}:\d{2}/';
                break;
            case 'YEAR':
                $rule = 'regex,regex:/\d{4}';
                break;
            case 'DATETIME':
                $rule = 'regex,regex:/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/';
                break;
            case 'TIMESTAMP':
                $rule = 'int,max:11';
                break;
            case 'CHAR':
                $rule = 'string,max:255';
                break;
            case 'VARCHAR':
                $rule = 'string,max:65535';
                break;
            case 'TINYBLOB':
                $rule = 'string,max:255';
                break;
            case 'TINYTEXT':
                $rule = 'string,max:255';
                break;
            case 'BLOB':
                $rule = 'string,max:65535';
                break;
            case 'TEXT':
                $rule = 'string,max:65535';
                break;
            case 'MEDIUMBLOB':
                break;
            case 'MEDIUMTEXT':
                break;
            case 'LONGBLOB':
            case 'LONGTEXT':
                break;
        }

        return $rule;
    }
}
